package es.us.lsi.daw.model.security;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import es.us.lsi.daw.annotations.Busqueda;
import es.us.lsi.daw.annotations.NoFiltrar;
import es.us.lsi.daw.annotations.Requerido;
import es.us.lsi.daw.annotations.Unico;
import es.us.lsi.daw.model.util.BaseEntity;

@Entity
@Table(name = Tables.USERS)
@Inheritance(strategy = InheritanceType.JOINED)
public class User extends BaseEntity implements Serializable, UserDetails {

	private static final long	serialVersionUID		= 1L;

	public static final String	A_USERNAME				= "username";
	public static final String	A_PASSWORD				= "password";
	public static final String	A_ENABLED				= "enabled";
	public static final String	A_GROUPS				= "groups";
	public static final String	A_ACCOUNT_LOCKED		= "accountLocked";
	public static final String	A_ACCOUNT_EXPIRED		= "accountExpired";
	public static final String	A_CREDENTIALS_EXPIRED	= "credentialsExpired";

	private static final String	C_USERNAME				= "username";
	private static final String	C_PASSWORD				= "password";
	private static final String	C_ENABLED				= "enabled";
	private static final String	C_ACCOUNT_LOCKED		= "account_locked";
	private static final String	C_ACCOUNT_EXPIRED		= "account_expired";
	private static final String	C_CREDENTIALS_EXPIRED	= "credentials_expired";
	
	
	public static final String	TJ_GROUP_MEMBERS		= Tables.GROUP_MEMBERS;
	
	public static final String	CJ_GROUP_MEMBERS_GROUPS	= "group_id";
	public static final String	CJ_GROUP_MEMBERS_USERS	= "user_id";
	
	@Unico
	@Requerido
	@Busqueda
	@Column(name = C_USERNAME)
	protected String				username;

	@Column(name = C_PASSWORD)
	protected String				password;

	@NoFiltrar
	@Column(name = C_ENABLED, columnDefinition = "BIT")
	protected boolean			enabled;
	
	@NoFiltrar
	@Column(name = C_ACCOUNT_LOCKED, columnDefinition = "BIT")
	protected boolean			accountLocked;
	
	@NoFiltrar
	@Column(name = C_ACCOUNT_EXPIRED, columnDefinition = "BIT")
	protected boolean			accountExpired;
	
	@NoFiltrar
	@Column(name = C_CREDENTIALS_EXPIRED, columnDefinition = "BIT")
	protected boolean			credentialsExpired;

	@ManyToMany(fetch=FetchType.EAGER) 
	@JoinTable(
			name = TJ_GROUP_MEMBERS,
			joinColumns=@JoinColumn(name = CJ_GROUP_MEMBERS_USERS),
			inverseJoinColumns=@JoinColumn(name = CJ_GROUP_MEMBERS_GROUPS)
			)
	protected Set<Group>			groups;
	
	/**
	 * Copy constructor
	 * @param user
	 */
	public User(User user) {
		this.username = user.username;
		this.password = user.password;
		this.enabled = user.enabled;
		this.accountLocked = user.accountLocked;
		this.accountExpired = user.accountExpired;
		this.credentialsExpired = user.credentialsExpired;
		this.groups = user.groups;
	}

	public User() {
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Set<Group> getGroups() {
		return groups;
	}

	public void setGroups(Set<Group> groups) {
		this.groups = groups;
	}

	public boolean isAccountLocked() {
		return accountLocked;
	}

	public boolean isAccountExpired() {
		return accountExpired;
	}

	public boolean isCredentialsExpired() {
		return credentialsExpired;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	public void setAccountLocked(boolean accountLocked) {
		this.accountLocked = accountLocked;
	}

	public void setAccountExpired(boolean accountExpired) {
		this.accountExpired = accountExpired;
	}

	public void setCredentialsExpired(boolean credentialsExpired) {
		this.credentialsExpired = credentialsExpired;
	}

	public String getPassword() {
		return password;
	}
	
	public boolean isAccountNonExpired() {
		return !accountExpired;
	}

	public boolean isAccountNonLocked() {
		return !accountLocked;
	}

	public boolean isCredentialsNonExpired() {
		return !credentialsExpired;
	}

	public boolean isEnabled() {
		return enabled;
	}

	public Collection<? extends GrantedAuthority> getAuthorities() {
		Set<Authority> authorities = new HashSet<Authority>();
		for (Group g : getGroups())
			authorities.addAll(g.getAuthorities());
		return authorities;
	}

	public String getUsername() {
		return username;
	}

	
}
